package xio.ccf_201509;

import java.util.*;

/**
 * 201509-4 高速公路 100分 代码同ccf_201709 通信网络 类似
 * Created by ywb47 on 2017/10/29.
 */
public class Highway {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        int m = sc.nextInt();
        Digraph g = new Digraph(n);
        for (int i = 1; i <= m; i++) {
            int v = sc.nextInt();
            int w = sc.nextInt();
            g.addEdge(v,w);
        }
        Kosaraju kosaraju = new Kosaraju(g);
        int sccCount = kosaraju.count();
        int result = 0;
        for (int i = 0; i < sccCount; i++) {
        	int vCount = kosaraju.sscV(i);
//        	 System.out.println(vCount+"  sscCount");
        	if (vCount >=2) {
				result = result+ (vCount * (vCount-1))/2;
			}
		}

        System.out.println(result+"");
        
    }
     

    static class Digraph{
        private int V;
        private int E;
        private List<LinkedHashSet<Integer>> adj;
        Digraph(int N){
            this.V = N;
            this.E = 0;
            adj = new ArrayList<>();
            for (int i = 0; i <= V; i++) {
                adj.add(new LinkedHashSet<Integer>());
            }
        }

        public void addEdge(int v,int w){
            adj.get(v).add(w);
            E++;
        }

        public LinkedHashSet<Integer> adj(int v){
           return adj.get(v);
        }

        public Digraph reverse(){
            Digraph d = new Digraph(V);
            for (int i = 1; i <= V; i++) {
                for (int w : adj(i)) {
                    d.addEdge(w,i);
                }
            }
            return d;

        }

        public int V(){
            return V;
        }

        public int E(){
            return E;
        }
    }

    static class DepthFirstOrder{
        private boolean[] marked;
        private Stack<Integer> reversePost;

        DepthFirstOrder(Digraph g){
            reversePost = new Stack<>();
            marked = new boolean[g.V()+1];
            for (int i = 1; i <= g.V(); i++) {
               if (!marked[i]) dfs(g,i);
            }
        }

        private void dfs(Digraph g,int v){
            marked[v] = true;
            for (Integer i : g.adj(v)) {
                if (!marked[i]){
                    dfs(g,i);
                }
            }
            reversePost.push(v);
        }

        public Stack<Integer> reversePost(){
            return reversePost;
        }
    }

    static class Kosaraju{
        private boolean[] marked;
        private int[] id;
        private int count = 0;
        private int[] sscV;

        Kosaraju(Digraph g){
            marked = new boolean[g.V()+1];
            id = new int[g.V()+1];
            sscV = new int[g.V()+1];
            DepthFirstOrder order = new DepthFirstOrder(g.reverse());
            Stack<Integer> reversePost = order.reversePost();
           while (!reversePost.isEmpty()){
               int i = reversePost.pop();
                if (!marked[i]) {
                    dfs(g,i);
                    count++;
                }
            }
        }

        private void dfs(Digraph g, int v) {
            marked[v] = true;
            id[v] = count;
            sscV[count]++;
            for (Integer i : g.adj(v)) {
                if (!marked[i]){
                    dfs(g,i);
                }
            }
        }

        public int sscV(int id){
            return sscV[id];
        }

        public int id(int v){
            return id[v];
        }
        public int count(){
            return count;
        }
    }

}
